package cn.bugstack.domain.order.service;

import cn.bugstack.domain.order.adapter.repository.IOrderRepository;
import cn.bugstack.domain.order.adapter.port.IProductPort;
import cn.bugstack.domain.order.model.aggregate.CreateOrderAggregate;
import cn.bugstack.domain.order.model.entity.*;
import cn.bugstack.domain.order.model.valobj.OrderStatusVO;
import cn.bugstack.types.common.Constants;
import cn.bugstack.types.enums.MarketTypeVO;
import cn.bugstack.types.exception.AppException;
import com.alipay.api.AlipayApiException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomStringUtils;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;

@Slf4j
public abstract class AbstractOrderService implements IOrderService {
    protected final IOrderRepository repository;
    protected final IProductPort port;

    public AbstractOrderService(IOrderRepository repository, IProductPort port) {
        this.repository = repository;
        this.port = port;
    }


    @Override
    public PayOrderEntity createOrder(ShopCartEntity shopCartEntity) throws Exception {
        OrderEntity paidOrder = repository.queryPayOrder(shopCartEntity);
        if (paidOrder!=null){
            if (paidOrder.getOrderStatusVO().equals(OrderStatusVO.PAY_SUCCESS) || paidOrder.getOrderStatusVO().equals(OrderStatusVO.DEAL_DONE) || paidOrder.getOrderStatusVO().equals(OrderStatusVO.MARKET)) {
                throw new AppException(Constants.ResponseCode.MORE_JOINERROR.getCode(), Constants.ResponseCode.UN_ERROR.getInfo());
            }
        }

        // 1. 查询当前用户是否存在未支付订单或掉单订单
        OrderEntity unpaidOrder = repository.queryUnPayOrder(shopCartEntity);
        if (unpaidOrder != null && unpaidOrder.getOrderStatusVO().equals(OrderStatusVO.PAY_WAIT)) {
            log.info("创建订单-存在，已存在未支付订单。userId:{} productId:{} orderId:{}", shopCartEntity.getUserId(), shopCartEntity.getProductId(), unpaidOrder.getOrderId());
            return PayOrderEntity.builder()
                    .orderId(unpaidOrder.getOrderId())
                    .payUrl(unpaidOrder.getPayUrl())
                    .orderStatusVO(unpaidOrder.getOrderStatusVO())
                    .build();
        } else if (unpaidOrder != null && OrderStatusVO.CREATE.equals(unpaidOrder.getOrderStatusVO())) {
            Integer marketType = unpaidOrder.getMarketType();
            BigDecimal marketDeductionAmount = unpaidOrder.getMarketDeductionAmount();
            PayOrderEntity payOrderEntity = null;
            if (marketType.equals(MarketTypeVO.GROUP_BUY_MARKET.getCode()) && null == marketDeductionAmount) {
                MarketPayDiscountEntity marketPayDiscountEntity = this.lockMarketPayOrder(shopCartEntity.getUserId(),
                        shopCartEntity.getTeamId(),
                        shopCartEntity.getActivityId(),
                        shopCartEntity.getProductId(),
                        unpaidOrder.getOrderId());
                payOrderEntity = doPrepayOrder(shopCartEntity.getUserId(),
                        shopCartEntity.getProductId(),
                        unpaidOrder.getProductName(),
                        unpaidOrder.getOrderId(),
                        unpaidOrder.getTotalAmount(),
                        marketPayDiscountEntity);

            } else if (MarketTypeVO.GROUP_BUY_MARKET.getCode().equals(marketType)) {
                payOrderEntity = doPrepayOrder(shopCartEntity.getUserId(), shopCartEntity.getProductId(),
                        unpaidOrder.getProductName(), unpaidOrder.getOrderId(), unpaidOrder.getPayAmount());

            } else {
                payOrderEntity = doPrepayOrder(shopCartEntity.getUserId(), shopCartEntity.getProductId(),
                        unpaidOrder.getProductName(), unpaidOrder.getOrderId(), unpaidOrder.getTotalAmount());
            }
            return PayOrderEntity.builder()
                    .orderId(payOrderEntity.getOrderId())
                    .payUrl(payOrderEntity.getPayUrl())
                    .orderStatusVO(unpaidOrder.getOrderStatusVO())
                    .build();
        }

        // 2. 查询商品 & 创建订单
        ProductEntity productEntity = port.queryProductByProductId(shopCartEntity.getProductId());
        // 订单实体信息
        OrderEntity orderEntity = CreateOrderAggregate.bulidOrderEntity(productEntity.getProductId(), productEntity.getProductName(), shopCartEntity.getMarketTypeVO());
        // 订单聚合对象
        CreateOrderAggregate orderAggregate = CreateOrderAggregate.builder()
                .userId(shopCartEntity.getUserId())
                .orderEntity(orderEntity)
                .productEntity(productEntity)
                .build();
        // 创建本地订单
        this.doSaveOrder(orderAggregate);

        // 发起营销锁单
        MarketPayDiscountEntity marketPayDiscountEntity = null;
        if (MarketTypeVO.GROUP_BUY_MARKET.equals(shopCartEntity.getMarketTypeVO())) {
            marketPayDiscountEntity = this.lockMarketPayOrder(shopCartEntity.getUserId(),
                    shopCartEntity.getTeamId(),
                    shopCartEntity.getActivityId(),
                    shopCartEntity.getProductId(),
                    orderEntity.getOrderId()
            );
        }

        //创建支付单
        PayOrderEntity payOrder = doPrepayOrder(shopCartEntity.getUserId(),
                productEntity.getProductId(),
                productEntity.getProductName(),
                orderEntity.getOrderId(),
                productEntity.getPrice(),
                marketPayDiscountEntity
        );

        log.info("创建订单-完成，生成支付单。userId: {} orderId: {} payUrl: {}", shopCartEntity.getUserId(), orderEntity.getOrderId(), payOrder.getPayUrl());

        return PayOrderEntity.builder()
                .orderId(orderEntity.getOrderId())
                .payUrl(payOrder.getPayUrl())
                .orderStatusVO(payOrder.getOrderStatusVO())
                .build();
    }

    protected abstract MarketPayDiscountEntity lockMarketPayOrder(String userId, String teamId, Long activityId, String productId, String orderId);

    protected abstract PayOrderEntity doPrepayOrder(String userId, String productId, String productName, String orderId, BigDecimal totalAmount) throws AlipayApiException;

    protected abstract PayOrderEntity doPrepayOrder(String userId, String productId, String productName, String orderId, BigDecimal price, MarketPayDiscountEntity marketPayDiscountEntity) throws AlipayApiException;

    protected abstract void doSaveOrder(CreateOrderAggregate orderAggregate);

    @Override
    public List<OrderEntity> queryUserOrderList(String userId, Long lastId, Integer pageSize) {
        return repository.queryUserOrderList(userId, lastId, pageSize);
    }

}
